package com.zx.platform.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA. User: Administrator Date: 14-12-10 Time: 下午9:21 To
 * change this template use File | Settings | File Templates.
 */
public class PmpUtils {

	private static final String Algorithm = "DESede";// 定义 加密算法,可用

	/**
	 * 获得一个UUID
	 * 
	 * @return String UUID
	 */
	public static String getUUID() {
		String s = UUID.randomUUID().toString();
		// 去掉“-”符号
		return s.replaceAll("-", "");
	}

	/**
	 * 将数据流转换成指定的字符集字符串
	 * 
	 * @param in
	 *            数据流
	 * @param encoding
	 *            字符集编码
	 * @return String 字符串
	 */
	public static String inputStream2String(InputStream in, String encoding)
			throws IOException {
		StringBuffer sb = new StringBuffer();
		InputStreamReader isr = new InputStreamReader(in, encoding);

		char[] b = new char[4096];
		for (int n; (n = isr.read(b)) != -1;) {
			sb.append(new String(b, 0, n));
			// System.out.println(n);
		}
		return sb.toString();
	}

	/**
	 * 加密方法
	 * 
	 * @param src
	 *            源数据的字节数组
	 * @return
	 */
	public static String encryptMode(String key, byte[] src) {
		try {
			SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm); // 生成密钥
			Cipher c1 = Cipher.getInstance(Algorithm); // 实例化负责加密/解密的Cipher工具类
			c1.init(Cipher.ENCRYPT_MODE, deskey); // 初始化为加密模式
			byte[] encryptedByteArray = c1.doFinal(src);
			// 加密运算之后 将byte[]转化为base64的String
			BASE64Encoder enc = new BASE64Encoder();
			return enc.encode(encryptedByteArray);
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密函数
	 * 
	 * @param src
	 *            密文的字节数组
	 * @return
	 */
	public static byte[] decryptMode(String key, String src) {
		try {
			SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm);
			Cipher c1 = Cipher.getInstance(Algorithm);
			c1.init(Cipher.DECRYPT_MODE, deskey); // 初始化为解密模式
			BASE64Decoder dec = new BASE64Decoder();
			byte[] encryptedByteArray = dec.decodeBuffer(src);
			// 解密运算 将base64的String转化为byte[]
			return c1.doFinal(encryptedByteArray);
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	/*
	 * 根据字符串生成密钥字节数组
	 * 
	 * @param keyStr 密钥字符串
	 * 
	 * @return
	 * 
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] build3DesKey(String keyStr)
			throws UnsupportedEncodingException {
		byte[] key = new byte[24]; // 声明一个24位的字节数组，默认里面都是0
		byte[] temp = keyStr.getBytes("UTF-8"); // 将字符串转成字节数组

		/*
		 * 执行数组拷贝 System.arraycopy(源数组，从源数组哪里开始拷贝，目标数组，拷贝多少位)
		 */
		if (key.length > temp.length) {
			// 如果temp不够24位，则拷贝temp数组整个长度的内容到key数组中
			System.arraycopy(temp, 0, key, 0, temp.length);
		} else {
			// 如果temp大于24位，则拷贝temp数组24个长度的内容到key数组中
			System.arraycopy(temp, 0, key, 0, key.length);
		}
		return key;
	}

	/**
	 * md5加密
	 * 
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static final String encoderByMD5(String str)
			throws UnsupportedEncodingException {
		return DigestUtils.md5Hex(str.getBytes("utf-8"));
	}
	

	public static int getPageCount(int recordCount, int pageSize) {
		Double count = Math.ceil(1.0 * recordCount / pageSize);
		return count.intValue();
	}

	/**
	 * 获取订单号
	 * 
	 * @return
	 */
	public static final String getOrderNum() {
		return  getCommonOrder();
	}

	/**
	 * 获取充值订单号
	 * 
	 * @return
	 */
	public static final String getRechargeOrderNum() {
		return "RC"+ getCommonOrder();
	}

	/**
	 * 获取订单号
	 * 
	 * @return
	 */
	public static final String getPayOrderNum() {
		return "P" + getCommonOrder();
	}

	/**
	 * 获取取现订单号
	 * 
	 * @return
	 */
	public static final String getEncashOrderNum() {
		return "E" +  getCommonOrder();
	}

	/**
	 * 获取信用还款订单号
	 * 
	 * @return
	 */
	public static final String getCreditRepayOrderNum() {
		return "CR" +  getCommonOrder();
	}

	/**
	 * 获取无卡订单号
	 * 
	 * @return
	 */
	public static final String getNoCardOrderNum() {
		return "N" + getCommonOrder();
	}

	/**
	 * 获取刷卡收款订单号
	 * 
	 * @return
	 */
	public static final String getCardOrderNum() {
		return "C" + getCommonOrder();
	}

	/**
	 * 获取消费订单号
	 * 
	 * @return
	 */
	public static final String getConsumeOrderNum() {
		return "GA" + getCommonOrder();
	}

	/**
	 * 获取分享收益订单号
	 * 
	 * @return
	 */
	public static final String getShareProfitOrderNum() {
		return "SP" +  getCommonOrder();
	}


	private static String getCommonOrder() {
		String  rannum= RandomStringUtils.random(5,false,true);// 获取随机数
		String nowTimeStr = TmDateUtil.nowTime(TmDateUtil.TIMESTAMP_FOMART_OTHER); // 当前时间
		return nowTimeStr+rannum;
	}
	
	/**
	 * 获取请求IP
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		try {
			String ip = request.getHeader(" x-forwarded-for ");
			if (ip == null || ip.length() == 0
					|| " unknown ".equalsIgnoreCase(ip)) {
				ip = request.getHeader(" Proxy-Client-IP ");
			}
			if (ip == null || ip.length() == 0
					|| " unknown ".equalsIgnoreCase(ip)) {
				ip = request.getHeader(" WL-Proxy-Client-IP ");
			}
			if (ip == null || ip.length() == 0
					|| " unknown ".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
			return ip;
		} catch (Exception ex) {
			return "unknown";
		}
	}

	/**
	 * "yyyy-MM-dd HH:mm:ss"
	 * 
	 * @param strDate
	 * @param format
	 * @return
	 */
	public static Date strToDate(String strDate, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		ParsePosition pos = new ParsePosition(0);
		return formatter.parse(strDate, pos);
	}

	/**
	 * "yyyy-MM-dd HH:mm:ss"
	 * 
	 * @param date
	 * @param format
	 * @return
	 */
	public static String dateToString(Date date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		return formatter.format(date);
	}

	public static String getRandomString(int length) { // length表示生成字符串的长度
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	public static String getNumberRandomString(int length) { // length表示生成字符串的长度
		String base = "0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * 获取日期
	 * 
	 * @param date
	 * @param tianshu
	 * @return
	 */
	public static Date addDate(Date date, int tianshu) {
		Date returnDate = new Date();
		long Time = (date.getTime() / 1000) + 24 * 60 * 60 * tianshu;
		returnDate.setTime(Time * 1000);
		return returnDate;
	}

	/**
	 * 手机号验证
	 * 
	 * @param mobiles
	 * @return
	 */
	public static boolean isMobileNo(String mobiles) {
		Pattern p = Pattern
				.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9])|(17[0-9]))\\d{8}$");
		Matcher m = p.matcher(mobiles);
		return m.matches();
	}

	/**
	 * 功能：身份证的有效验证
	 * 
	 * @param IDStr
	 *            身份证号
	 * @return 有效：返回"" 无效：返回String信息
	 */
	public static boolean idCardValidate(String IDStr) {
		boolean errorInfo = true;// 记录错误信息
		String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4",
				"3", "2" };
		String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
				"9", "10", "5", "8", "4", "2" };
		String Ai = "";
		// ================ 号码的长度 15位或18位 ================
		if (IDStr.length() != 15 && IDStr.length() != 18) {
			errorInfo = false;
			return errorInfo;
		}
		// ================ 数字 除最后以为都为数字 ================
		if (IDStr.length() == 18) {
			Ai = IDStr.substring(0, 17);
		} else if (IDStr.length() == 15) {
			Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);
		}
		if (isNumeric(Ai) == false) {
			errorInfo = false;
			return errorInfo;
		}
		// ================ 判断最后一位的值 ================
		int TotalmulAiWi = 0;
		for (int i = 0; i < 17; i++) {
			TotalmulAiWi = TotalmulAiWi
					+ Integer.parseInt(String.valueOf(Ai.charAt(i)))
					* Integer.parseInt(Wi[i]);
		}
		int modValue = TotalmulAiWi % 11;
		String strVerifyCode = ValCodeArr[modValue];
		Ai = Ai + strVerifyCode;

		if (IDStr.length() == 18) {
			if (Ai.equals(IDStr) == false) {
				errorInfo = false;
				return errorInfo;
			}
		} else {
			errorInfo = true;
		}
		// =====================(end)=====================
		return errorInfo;
	}

	/**
	 * 功能：判断字符串是否为数字
	 * 
	 * @param str
	 * @return
	 */
	private static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (isNum.matches()) {
			return true;
		} else {
			return false;
		}
	}

	public static void main(String[] ags) throws UnsupportedEncodingException,
			NoSuchAlgorithmException {
		// MessageDigest md5 = MessageDigest.getInstance("MD5");
		// System.out.println(md5.("123456"));
		System.out.println(PmpUtils.idCardValidate("622103198705265518"));
	}

	//获得IP  add by wenjw 2016.12.14
	public static InetAddress getInetAddress() {
		try {
			return InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			System.out.println("unknown host!");
		}
		return null;

	}

	public static String getHostIp(InetAddress netAddress) {
		if (null == netAddress) {
			//return null;
			netAddress = getInetAddress(); 
		}
		String ip = netAddress.getHostAddress(); // get the ip address
		return ip;
	}

	public static String getHostName(InetAddress netAddress) {
		if (null == netAddress) {
			//return null;
			netAddress = getInetAddress();
		}
		String name = netAddress.getHostName(); // get the host address
		return name;
	}
	/**
	 * 获取月份
	 * @param date
	 * @param range -1
	 * @return
	 */
	public static Map<String, String> getRangeDate(Date date, int range ) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, range); 
		int lastMonthMaxDay=calendar.getActualMaximum(Calendar.DAY_OF_MONTH); 
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);
		String endDate = sdf.format(calendar.getTime());
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01  00:00:00");
		String startDate = sdf2.format(calendar.getTime());
		Map<String, String> result = new HashMap<>();
		result.put("startDate", startDate);
		result.put("endDate", endDate);
		return result;
		
	}
	/**
	 * 获取时间区间
	 * @param startDate
	 * @param endDate
	 * @param range
	 * @return
	 */
	public static List<String> getDateList(Date startDate, Date endDate, String dateType){
		List<String> result = new ArrayList<>();
		
		switch(dateType) {
			case "day":
				Calendar cds = Calendar.getInstance();  
				cds.setTime(startDate);
				
				Calendar cde = Calendar.getInstance();  
				cde.setTime(endDate);
				
				long val = cde.getTimeInMillis() - cds.getTimeInMillis();  
				long day = val / (1000 * 60 * 60 * 24);
				result.add(dateToString(cds.getTime(), "yyyy-MM-dd"));
				while(day > 0) {
					cds.add(Calendar.DAY_OF_YEAR, 1);
					result.add(dateToString(cds.getTime(), "yyyy-MM-dd"));
					day--;
				}
				break;
			case "week":
				Calendar cws = Calendar.getInstance();
				cws.setTime(startDate);
				cws.set(Calendar.DAY_OF_WEEK, 2);
				Date startWeek = cws.getTime();
				
				Calendar cwe = Calendar.getInstance();
				cwe.setTime(endDate);
				cwe.set(Calendar.DAY_OF_WEEK, 2);
				Date endWeek = cwe.getTime();
				result.add(dateToString(startWeek, "yyyy-MM-dd"));
				while(endWeek.after(startWeek)) {
					cws.add(Calendar.DATE, 7);
					startWeek = cws.getTime();
					
					result.add(dateToString(startWeek, "yyyy-MM-dd"));
				}
				break;
			case "month":
				Calendar cms = Calendar.getInstance();
				cms.setTime(startDate);
				cms.set(Calendar.DAY_OF_MONTH, 1);
				Date startMonth = cms.getTime();
				
				Calendar cme = Calendar.getInstance();
				cme.setTime(endDate);
				cme.set(Calendar.DAY_OF_MONTH, 1);
				Date endMonth = cme.getTime();
				result.add(dateToString(startMonth, "yyyy-MM"));
				while(endMonth.after(startMonth)) {
					cms.add(Calendar.MONTH, 1);
					startMonth = cms.getTime();
					result.add(dateToString(startMonth, "yyyy-MM"));
				}
				break;
			case "hour":
				int startHour = 0, endHour = 24;
				while(endHour >= startHour) {
					result.add(String.valueOf(startHour));
					startHour++;
				}
				break;
		}

		return result;
	}
	/**
	 * 获取前提天的时间：是否包含时分秒
	 * @param date
	 * @param hasHMS
	 * @return
	 */
	public static Date getYesterday(Date date, boolean hasHMS) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, -1);
		if(hasHMS) {
			calendar.set(Calendar.HOUR, 0);
			calendar.set(Calendar.MINUTE, 0);
			calendar.set(Calendar.SECOND, 0);
		}
		return calendar.getTime();
	}
	/**
	 * 处理接口时间格式
	 * @param params
	 * @return
	 */
	public static Map<String, Date> translateDate(Map params){
		Map<String, Date> result = new HashMap<>();
		if(params.containsKey("beginDate") && params.containsKey("endDate") && StringUtils.isNoneBlank((String)params.get("beginDate")) && StringUtils.isNoneBlank((String)params.get("endDate"))) {
			result.put("beginDate", strToDate((String)params.get("beginDate") + " 00:00:00","yyyy-MM-dd 00:00:00"));
			result.put("endDate", addDate(strToDate((String)params.get("endDate") + " 00:00:00","yyyy-MM-dd 00:00:00"), 1));
		}
		return result;
	}
	
	public static Map<String, Date> dateAddHms(Date beginDatetime, Date endDatetime){
		Map<String, Date> result = new HashMap<>();
		String hms = dateToString(new Date(), " HH:mm:ss");
		if(Objects.nonNull(beginDatetime) && Objects.nonNull(endDatetime)) {
			result.put("beginDatetime", strToDate(dateToString(beginDatetime, "yyyy-MM-dd") + hms,"yyyy-MM-dd HH:mm:ss"));
			result.put("endDatetime", strToDate(dateToString(endDatetime, "yyyy-MM-dd") + hms,"yyyy-MM-dd HH:mm:ss"));
		}
		return result;
	}
}
